using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Me.Prettyprint.Cassandra.Connection.Client;
using Me.Prettyprint.Cassandra.Connection.Factory;
using Me.Prettyprint.Cassandra.Service;
using Me.Prettyprint.Cassandra.Utils;
using Me.Prettyprint.Hector.Api.Exceptions;

namespace Me.Prettyprint.Cassandra.Connection
{
    /// <summary>
    /// Implementation is simple, it does a sort by comparing the number of active
    /// connections in the host pool and returns the one that is least active.
    /// </summary>
	[Serializable]
	public class LeastActiveBalancingPolicy : LoadBalancingPolicy
	{
        private Logger logger = new Logger(typeof(LeastActiveBalancingPolicy));

		public LeastActiveBalancingPolicy()
		{
		}
        public HClientPool GetPool(ICollection<HClientPool> pools, List<CassandraHost> excludeHosts)
        {
            Dictionary<CassandraHost, HClientPool> pooldictionary = new Dictionary<CassandraHost, HClientPool>();
            foreach (HClientPool p in pools)
            {
                pooldictionary.Add(p.CassandraHost, p);
            }
            if (excludeHosts != null)
            {
                foreach (CassandraHost host in excludeHosts)
                {
                    if (pooldictionary.ContainsKey(host))
                    {
                        pooldictionary.Remove(host);
                    }
                }
            }
            List<HClientPool> sublist = new List<HClientPool>(pooldictionary.Values);
            sublist.Shuffle();
            sublist.Sort(new ShufflingCompare(this));
            HClientPool pool = sublist[0];
            logger.Info(" -------- " + pool.CassandraHost.Ip + " -------------");
            return pool;
        }
        public HClientPool CreateConnection(HClientFactory clientFactory, CassandraHost host, CassandraClientMonitor monitor)
        {
            return new ConcurrentHClientPool(clientFactory, host, monitor);
        }

        // Class for comparing HClientPool that compares the number of active connections
        private sealed class ShufflingCompare : System.Collections.Generic.IComparer<HClientPool>
		{
			public ShufflingCompare(LeastActiveBalancingPolicy enclosingInstance)
			{
                LoadBalancingPolicy = enclosingInstance;
			}
            public LeastActiveBalancingPolicy LoadBalancingPolicy
            {
                get;
                set;
            }
			public int Compare(HClientPool o1, HClientPool o2)
			{
				return o1.NumActive - o2.NumActive;
			}
			public System.Int32 Compare(System.Object x, System.Object y)
			{
				return 0;
			}
		}

    }
}